package com.dg.gaming.server.data.mysql;

import java.io.*;
import java.lang.reflect.*;
import java.sql.*;
import java.util.*;

import com.dg.gaming.api.common.*;
import com.dg.gaming.server.helper.*;
import javolution.util.*;
import nanoxml.*;
import javax.sql.*;
import org.apache.commons.dbcp.*;

/**
 * <p>Title: </p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author not attributable
 * @version 1.0
 */
public class DBManager {

    private static BasicDataSource ds = null;

    public static void init() {
        ds = setupDataSource("com.mysql.jdbc.Driver",
                             "jdbc:mysql://localhost/dg",
                             "dg",
                             "1", 5);

    }

    public static BasicDataSource setupDataSource(String driver,
                                                  String connectURI,
                                                  String username,
                                                  String psssword,
                                                  int poolsize) {
        BasicDataSource ds = new BasicDataSource();
        ds.setDriverClassName(driver);
        ds.setUsername(username);
        ds.setPassword(psssword);
        ds.setUrl(connectURI);
        ds.setInitialSize(poolsize);
        ds.setInitialSize(poolsize);
        ds.setPoolPreparedStatements(true);
        ds.setDefaultAutoCommit(false);

        return ds;
    }

    private final static ThreadLocal<Connection> connections = new ThreadLocal<
            Connection>();
    private static List<PrepareStatmentObject> psList = Collections.
            synchronizedList(new
                             FastList<PrepareStatmentObject>());

    static {
        psList.add(DBUser.PSO_LOAD_FULL);
        psList.add(DBUser.PSO_LOAD_FULL_WITH_ID);

        psList.add(DBGame.PSO_LOAD_FULL);
        psList.add(DBGame.PSO_LOAD_SIMPLE);
        psList.add(DBGame.PSO_SAVE);

        psList.add(DBCurrentTable.PSO_SAVE);
        psList.add(DBCurrentTable.PSO_LOAD_FULL);

    }

    public synchronized static DBUser getDBUser(String username) throws
            Exception {
        Connection con = getConnection();
        try {
            DBUser dbUser = new DBUser();
            if (dbUser.load(username, con)) {
                return dbUser;
            } else {
                return null;
            }

        } finally {
            con.rollback();
            con.close();
        }
    }

    public synchronized static DBUser getDBUser(long userId) throws
            Exception {
        Connection con = getConnection();
        try {
            DBUser dbUser = new DBUser();
            if (dbUser.load(userId, con)) {
                return dbUser;
            } else {
                return null;
            }

        } finally {
            con.rollback();
            con.close();
        }
    }

    public static DBGame getDBGame(long gameId) throws
            Exception {
        DBGame game = new DBGame();
        Connection con = getConnection();
        try {
            if (game.loadFull(gameId, con)) {
                return game;
            } else {
                return null;
            }

        } finally {
            con.rollback();
            con.close();
        }

    }


    public static DBCurrentTable getDBCurrentTable(long tblId) throws
            Exception {
        DBCurrentTable game = new DBCurrentTable();
        Connection con = getConnection();
        try {
            if (game.loadFull(tblId, con)) {
                return game;
            } else {
                return null;
            }

        } finally {
            con.rollback();
            con.close();
        }

    }

    public static void saveDBCurrentTable(DBCurrentTable tbl) throws
            Exception {

        Connection con = getConnection();
        try {
            tbl.save(con);
        } finally {
            con.commit();
            con.close();
        }

    }


    private static Connection getConnection() throws Exception {
        Thread thread = Thread.currentThread();
        System.out.println("Getting connection for :" + thread.toString() +
                           " ID=" + thread.getId() +
                           " number of active connections " + ds.getNumActive());
        Connection con = ds.getConnection();
//        if (con == null) {
//            Class.forName("com.mysql.jdbc.Driver");
//            con = DriverManager.getConnection("jdbc:mysql://localhost/dg", "dg",
//                                              "1");
//            connections.set(con);
//            con.setAutoCommit(false);
//            for (PrepareStatmentObject elem : psList) {
//                elem.prepare(con);
//            }
//        }

        return con;
    }

    public static byte[] loadBytes(java.io.InputStream is) throws Exception {
        BufferedInputStream input = new BufferedInputStream(is);

        ByteArrayOutputStream buffer = new ByteArrayOutputStream(1024);
        byte[] data = new byte[1024];
        int numRead;

        while ((numRead = input.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, numRead);
        }
        input.close();
        return buffer.toByteArray();

    }

    public static void main(String[] args) {
        DataSource ds = setupDataSource("com.mysql.jdbc.Driver",
                                        "jdbc:mysql://localhost/dg",
                                        "dg",
                                        "1", 5);
        try {
            for (int i = 0; i < 5; i++) {
                System.out.println(ds.getConnection().hashCode());
            }
            System.out.println("");
        } catch (SQLException ex) {
        }
//        for (int i = 0; i < 1; i++) {
//            long time = System.currentTimeMillis();
//            try {
//                DBGame game = getDBGame(1);
//                MemoryClassLoader mcl = new MemoryClassLoader(DBGame.class.
//                        getClassLoader(), game.getData());
//                Class c = mcl.loadClass(game.getModelclassname());
////                Constructor cnst = c.getConstructor();
//                GameModel model = (GameModel) c.newInstance();
//                DBCurrentTable ct = getDBCurrentTable(1);
//                Table tbl = ct.getTable(model);
//                tbl.setModel(model);
//                tbl.addPlayer(new User("", 1, 0, 0, 0, 0, 0));
//                tbl.addPlayer(new User("", 2, 0, 0, 0, 0, 0));
//
//                Method m = c.getMethod("setData", Integer.TYPE, Integer.TYPE,
//                                       Integer.TYPE);
//                m.invoke(model, 0, 0, 1);
//                XMLElement elem = tbl.flatten();
//                elem.addChild(model.flatten());
//                ct.setMODELDATA(elem.toString().getBytes("UTF8"));
//                saveDBCurrentTable(ct);
//
//            } catch (Exception ex) {
//                ex.printStackTrace();
//            }
//
//        }
    }
}
